/**
 * 
 */
package com.xpec.c4.game.utility;

import java.math.BigDecimal;

/**
 * 計算一定時內的處理速度，並預估剩餘時間
 * <p>
 * <ul>
 * 使用流程
 * <li>有需要的話，設定預估要處理的工作總數 {@link #setEstimateTotalProcCount(long)}
 * <li>開始執行 {@link #start()}
 * <li>當一件工作完成時 {@link #increaseProcCount()}
 * <li>每隔一段時間需要計算處理速度時 {@link #calculateSpeed()}
 * <li>計算速度之後可以取得的資訊 {@link #getProcSpeed()}, {@link #getRemainTime()}
 * </ul>
 * 
 * @author TW15010
 * 
 */
public class ProcessSpeedCalculator {
	/**
	 * 預計要處理的總數量
	 */
	private long estimateTotalProcCount = 0;

	/**
	 * 開始處理的時間
	 */
	private long beginTime;

	/**
	 * 已經處理的數量
	 */
	private long totalProcCount;

	/**
	 * 計算一個週期內處理速度時的起始時間
	 */
	private long beginTimeForSpeedCal;

	/**
	 * 計算一個週期內處理速度時的處理數量
	 */
	private long procCountForSpeedCal;

	/**
	 * 計算出的目前週期處理速度
	 */
	private long procSpeed;

	/**
	 * 計算出的剩餘時間
	 */
	private long remainTime;

	/**
	 * 開始處理
	 */
	public void start() {
		beginTime = System.currentTimeMillis();
		totalProcCount = 0;

		beginTimeForSpeedCal = beginTime;
		procCountForSpeedCal = 0;
	}

	/**
	 * 完成的數量 +1
	 */
	public void increaseProcCount() {
		totalProcCount++;
		procCountForSpeedCal++;
	}

	/**
	 * 計算上一個週期到現在的處理速度
	 */
	public void calculateSpeed() {
		long takeTime = System.currentTimeMillis() - beginTimeForSpeedCal;
		procSpeed = procCountForSpeedCal;

		if (procCountForSpeedCal > 0 && estimateTotalProcCount > 0) {
			long remainCount = estimateTotalProcCount - totalProcCount;

			BigDecimal bTakeTime = new BigDecimal(takeTime);
			BigDecimal bProcSpeed = new BigDecimal(procSpeed);
			BigDecimal bRemainCount = new BigDecimal(remainCount);

			remainTime = bTakeTime.divide(bProcSpeed, 5, BigDecimal.ROUND_DOWN).multiply(bRemainCount).longValue();
		}

		beginTimeForSpeedCal = System.currentTimeMillis();
		procCountForSpeedCal = 0;
	}

	/**
	 * 設定預估的工作總數量
	 * 
	 * @param estimateTotalProcCount
	 *            工作總數
	 */
	public void setEstimateTotalProcCount(long estimateTotalProcCount) {
		this.estimateTotalProcCount = estimateTotalProcCount;
	}

	public long getTotalProcCount() {
		return totalProcCount;
	}

	/**
	 * 取得目前的處理速度
	 * 
	 * @return
	 */
	public long getProcSpeed() {
		return procSpeed;
	}

	/**
	 * 取得全部完成的預估剩餘時間
	 * 
	 * @return 預估剩餘時間
	 */
	public long getRemainTime() {
		return remainTime;
	}

	/**
	 * 取得到目前為止花費了多少時間
	 * 
	 * @return
	 */
	public long getTotalTakeTime() {
		return System.currentTimeMillis() - beginTime;
	}

	public long getEstimateTotalProcCount() {
		return estimateTotalProcCount;
	}

	/**
	 * 是否有指定預估工作總數
	 * 
	 * @return true: 是<br>
	 *         false: 否
	 */
	public boolean isHaveEstimateTotalProcCount() {
		if (estimateTotalProcCount > 0) {
			return true;
		}

		return false;
	}
}
